﻿''' <summary>
''' NCDC data (see http://www7.ncdc.noaa.gov/rest)
''' </summary>
''' <remarks></remarks>
Public Class clsNcdc
    Inherits clsWebProvider

    'the token is required. A single token allows only 60 queries per hour. It can be obtained from: http://www7.ncdc.noaa.gov/wsregistration/ws_home.html
    'TODO: it may be necessary to let the WRDB user get and enter their own token
    Private Token As String = "gagEEhbjEJHeHKKlKl"

    Private BaseURL As String = "http://www7.ncdc.noaa.gov/rest"

    Private Function DatasetID() As String
        Select Case NCDCDataType
            Case enumNCDCDataType.Daily : Return "daily"
            Case enumNCDCDataType.ISH : Return "ish"
            Case enumNCDCDataType.ISD : Return "isd"
            Case Else
                Return "ERROR!"
        End Select
    End Function

    Public Overrides ReadOnly Property Description As String
        Get
            Return "The NCDC (National Climatic Data Center) web service is still under development by the NCDC. Using this service, you can retrieve meteorologic data. Note that returned values will often need to be divided by 10 or 100 as they are stored as integers. Also, the Integrated Surface data date-time values are GMT, not local. For more information, see http://www7.ncdc.noaa.gov/rest."
        End Get
    End Property

    Public Overrides ReadOnly Property URL As String
        Get
            Return "www7.ncdc.noaa.gov/rest"
        End Get
    End Property

    Public Overrides Function GetStations(Optional NameFilter As String = "") As Boolean
        Try
            LastException = Nothing
            dictStations.Clear()
            dictAgencies.Clear()
            dictAgencies.Add("NCDC", New clsAgency("NCDC", "National Climatic Data Center"))

            'NCDC cannot query by lat/long box; instead, acquire entire huge station list from country or state

            Dim location As String = ""
            If SelectedCountryAbbrev = "US" Then
                If SelectedStateAbbrev = "" Then Return False
                location = String.Format("stateAbbrev/{0}", SelectedStateAbbrev)
            Else
                If SelectedCountryAbbrev = "" Then Return False
                location = String.Format("countryAbbrev/{0}", SelectedCountryAbbrev)
            End If

            'bug observed in daily service if query date in current year; bypass for now by excluding dates
            Dim daterange As String = ""
            If NCDCDataType <> enumNCDCDataType.Daily Then
                If EndDate > Now Then EndDate = Now 'bug if enter future date
                daterange = String.Format("{0:yyyyMMdd}/{1:yyyyMMdd}/", StartDate, EndDate)
            End If

            Dim url As String = String.Format("{0}/services/sites/{1}/{2}/{3}?output=xml&token={4}", BaseURL, DatasetID, location, daterange, Token)

            Dim ds As DataSet = Nothing
            If Not DownloadNwisData(url, ds) Then Return False

            If ds Is Nothing OrElse ds.Tables.Count = 0 Then Return False

            With ds.Tables(0)
                For Each r As DataRow In .Rows
                    Dim StationID As String = r("stationid")
                    Dim Lat As Double = r("lat")
                    Dim Lon As Double = r("lon")
                    Dim lowdate As String = TestNull(r("lowdate"), "")
                    Dim MinDate As Date = Date.MinValue
                    If lowdate.Length = 6 Then MinDate = New Date(lowdate.Substring(0, 4), lowdate.Substring(4, 2), 1)
                    Dim highdate As String = TestNull(r("highdate"), "")
                    Dim MaxDate As Date = Date.MaxValue
                    If highdate.Length = 6 Then MaxDate = (New Date(highdate.Substring(0, 4), highdate.Substring(4, 2), 1)).AddMonths(1)
                    If Not dictStations.ContainsKey(StationID) Then
                        With AreaOfInterest
                            If Lon >= .Left AndAlso Lon <= .Right AndAlso Lat >= .Top AndAlso Lat <= .Bottom AndAlso
                               MinDate < EndDate And MaxDate > StartDate Then
                                dictStations.Add(StationID, New clsStation(StationID, StationID, r("name"), DatasetID, "NCDC", "NCDC", Lat, Lon, "", "", r("elev"), lowdate & "-" & highdate))
                            End If
                        End With
                    End If
                Next
            End With
            Return True
        Catch ex As Exception
            LastException = ex
            Return False
        End Try
    End Function

    Public Overrides Function GetParameters(Optional NameFilter As String = "") As Boolean
        Try
            LastException = Nothing
            dictParameters.Clear()

            'note: the service call for "daily" is broken per 3/24/11 email with Rich Baldwin; 
            'hardwire the variables identified in this document: ftp://ftp.ncdc.noaa.gov/pub/data/documentlibrary/tddoc/td3200.doc

            If NCDCDataType = enumNCDCDataType.Daily Then
                With dictParameters
                    .Add("EVAP", New clsParameter("", "EVAP", "EVAP", "Daily evaporation", "Hundredths of Inches", 0, Now, Now))
                    .Add("MNPN", New clsParameter("", "MNPN", "MNPN", "Daily minimum temperature of water in an evaporation pan", "Deg F", 0, Now, Now))
                    .Add("MXPN", New clsParameter("", "MXPN", "MXPN", "Daily maximum temperature of water in an evaporation pan", "Deg F", 0, Now, Now))
                    .Add("PRCP", New clsParameter("", "PRCP", "PRCP", "Daily precipitation for 24 hours ending at time of observation. Trace is less than 0.005 inch", "Hundredths of Inches", 0, Now, Now))
                    .Add("SNOW", New clsParameter("", "SNOW", "SNOW", "Daily Snowfall for 24-hour period ending at observation time.  Trace is less than 0.05 inch", "Tenths of Inches", 0, Now, Now))
                    .Add("SNWD", New clsParameter("", "SNWD", "SNWD", "Snow depth at observation time. Trace is depth less than 0.5 inch", "Inches", 0, Now, Now))
                    .Add("TMAX", New clsParameter("", "TMAX", "TMAX", "Daily maximum temperature for 24 hours ending at time of observation", "Deg F", 0, Now, Now))
                    .Add("TMIN", New clsParameter("", "TMIN", "TMIN", "Daily minimum temperature for 24 hours ending at time of observation", "Deg F", 0, Now, Now))
                    .Add("TOBS", New clsParameter("", "TOBS", "TOBS", "Temperature at observation time", "Deg F", 0, Now, Now))
                    .Add("WDMV", New clsParameter("", "WDMV", "WDMV", "24-hour wind movement", "Miles", 0, Now, Now))
                    .Add("WTEQ", New clsParameter("", "WTEQ", "WTEQ", "Water equivalent of snow depth", "Tenths of Inches", 0, Now, Now))
                End With
            Else
                Dim url As String = String.Format("{0}/services/variables/{1}/?output=xml&token={2}", BaseURL, DatasetID, Token)
                Dim ds As DataSet = Nothing
                If Not DownloadNwisData(url, ds) OrElse ds Is Nothing Then Return False

                With ds.Tables(0)
                    For Each r As DataRow In .Rows

                        'may also want to call "variableinfo"

                        Dim Parm As String = r("abbrev")
                        Dim Name As String = r("name").Replace(" ***", "")
                        Dim Unit As String = r("unit")
                        If Not dictParameters.ContainsKey(Parm) Then
                            If NameFilter = "" OrElse Name.ToUpper.Contains(NameFilter.ToUpper) Then
                                dictParameters.Add(Parm, New clsParameter("", Parm, Parm, Name, Unit, 0, Now, Now))
                            End If
                        End If
                    Next
                End With
            End If
            Return True
        Catch ex As Exception
            LastException = ex
            Return False
        End Try
    End Function

    Public Overrides Function GetResults() As Boolean
        Try
            LastException = Nothing
            Cancelled = False
            lstData.Clear()
            DataCount = 0
            Dim cnt As Integer = 0
            For Each sta As String In SelectedStations
                For Each parm As String In SelectedParameters
                    If Not SetProgress(cnt, SelectedStations.Count * SelectedParameters.Count - 1, String.Format("Getting results for {0} ({1}); {2} values so far...", sta, parm, DataCount)) Then Return False
                    cnt += 1
                    Dim url As String = String.Format("{0}/services/values/{1}/{2}/{3}/{4:yyyyMMdd}/{5:yyyyMMdd}/?output=xml&token={6}", BaseURL, DatasetID, sta, parm, StartDate, EndDate, Token)
                    Dim ds As DataSet = Nothing

                    If Not DownloadNwisData(url, ds) Then Continue For

                    If ds Is Nothing OrElse ds.Tables.Count = 0 Then Continue For

                    With ds.Tables(0)
                        For Each r As DataRow In .Rows
                            Dim RCode As String = ""
                            Dim DateTime As Date = Date.MaxValue
                            Dim QCode As String = ""
                            Dim Result As Double = Double.MaxValue
                            Select Case NCDCDataType
                                Case enumNCDCDataType.Daily
                                    Dim yearMonth As String = r("yearMonth")
                                    Dim dayHour As String = r("dayHour")
                                    Dim Hour As Integer = dayHour.Substring(2, 2)
                                    If Hour = 99 Or Hour = 24 Then Hour = 0
                                    If yearMonth.Length = 6 And dayHour.Length = 4 Then DateTime = New Date(yearMonth.Substring(0, 4), yearMonth.Substring(4, 2), dayHour.Substring(0, 2), Hour, 0, 0)
                                    QCode = r("dataQuality")
                                    Result = r("metElement")
                                Case enumNCDCDataType.ISD, enumNCDCDataType.ISH
                                    Dim gmtDate As String = r("gmtDate")
                                    Dim gmtTime As String = r("gmtTime")
                                    If gmtDate.Length = 8 And gmtTime.Length = 4 Then DateTime = New Date(gmtDate.Substring(0, 4), gmtDate.Substring(4, 2), gmtDate.Substring(6, 2), gmtTime.Substring(0, 2), gmtTime.Substring(2, 2), 0)
                                    If IsNumeric(r("elemfld1")) Then Result = Val(r("elemfld1"))
                            End Select
                            If DateTime <> Date.MaxValue AndAlso Result <> -99999 AndAlso Result <> 99999 AndAlso Result <> Double.MaxValue Then
                                lstData.Add(New WRDB.Project.clsDataRecord(sta, DateTime, parm, Result, , , , , , , , , , QCode))
                                DataCount += 1
                            End If
                            If Cancelled Then Return False
                        Next
                    End With
                Next
            Next
            Return True
        Catch ex As Exception
            LastException = ex
            Return False
        End Try
        Return True
    End Function

End Class
